package com.anysoft.rrm;


import java.lang.reflect.Field;
import java.util.List;

import com.alogic.metrics.stream.MetricsCollector;
import com.alogic.metrics.stream.MetricsReportable;
import com.anysoft.stream.Flowable;
import com.anysoft.util.Pair;
import com.anysoft.util.Properties;
import com.anysoft.util.Reportable;

/**
 * Round Robin Data,可以放在RRM中的数据
 * 
 * @author duanyy
 * 
 * @version 1.6.4.42 [duanyy 20160407] <br>
 * - 对接指标处理器 <br>
 * 
 * @version 1.6.6.13 [20170109 duanyy] <br>
 * - 采用新的指标接口 <br>
 * 
 * @version 1.6.12.29 [20190409] <br>
 * - 优化指标输出模型，对接Prometheus;<br>
 * 
 * @version 1.6.12.32 [20190429] <br>
 * - 优化RRM模型
 */
public interface RRData extends Reportable,MetricsReportable, Flowable {
	
	/**
	 * 在现有数据上做加法
	 * 
	 * @param fragment 新的数据片段
	 */
	public void incr(RRData fragment);
	
	/**
	 * 克隆自身
	 * @return 新的片段
	 */
	public RRData copy();
	
	public void listAttrs(List<Pair<String,String>> list);
	
	/**
	 * 获取时间戳
	 * @return 时间戳
	 */
	public long timestamp();
	
	/**
	 * 设置时间戳
	 * @param t 时间
	 */
	public void timestamp(long t);
	
	/**
	 * 获取指标id
	 * @return 指标id
	 */
	public String id();
	
	/**
	 * 虚基类
	 * @author duanyy
	 *
	 */
	public abstract static class Abstract implements RRData{
		protected String id = "unknown";
		
		protected long timestamp;
		
		public Abstract(String metricsId){
			id = metricsId;
		}
		
		public void setId(String metricsId){
			this.id = metricsId;
		}
		
		public String id(){
			return id;
		}
		
		@Override
		public long timestamp() {
			return timestamp;
		}

		@Override
		public void timestamp(long t) {
			timestamp = t;
		}
		
		@Override
		public void listAttrs(List<Pair<String,String>> list){
			
		}
		
		@Override
		public void report(MetricsCollector collector,Properties p) {
			report(collector);
		}

		public abstract void report(MetricsCollector collector);

		@Override
		public String getStatsDimesion() {
			return id();
		}

		@Override
		public boolean isAsync() {
			return true;
		}

		@Override
		public String getValue(String varName, Object context, String defaultValue) {
			Class<? extends Abstract> clazz = this.getClass();
			Field[] fields = clazz.getDeclaredFields();
			
			for (Field f:fields){
				if (f.getName().equals(varName) && f.isAccessible()){
					try {
						Object obj =  f.get(this);
						if (obj != null){
							return obj.toString();
						}
					}catch (Exception ex){
						break;
					}
				}
			}
			
			return defaultValue;
		}

		@Override
		public String getRawValue(String varName, Object context, String dftValue) {
			return getValue(varName,context,dftValue);
		}

		@Override
		public Object getContext(String varName) {
			return this;
		}
	}
}
